package ro.flashbite.game_engine.controller
{	
	import ro.flashbite.errors.ArgumentIncompatibleError;
	import ro.flashbite.errors.SingletonError;
	import ro.flashbite.interfaces.ISleepWakeupDestroy;
	import ro.flashbite.game_engine.interfaces.IAppNotifier;

	/**
	 * Basic Observer pattern in action
	 * Each application part who needs 'acces' to sleep, wakeup, destroy from global application, must subscribe to it
	 * 
	 * v 1.0
	 *  
	 * @author Adrian Barbu
	 */	
	public final class AppStateNotifier implements ISleepWakeupDestroy, IAppNotifier
	{
		/**
		 * static singleton instance 
		 */		
		private static var _instance:	AppStateNotifier;
		
		/**
		 * registered observers to be notified 
		 */		
		private var _observers		:	Vector.<ISleepWakeupDestroy>;
		/**
		 * observers count 
		 */		
		private var _obsLength		:	uint;
		/**
		 * performance int counter used in for loop
		 */		
		private var _counter		:	int;
		
		// ================================================================================================================================
		// CONSTRUCTOR
		// ================================================================================================================================
		
		public function AppStateNotifier(enforcer:SingletonEnforcer)
		{
			if (enforcer == null) throw new SingletonError();
			
			_observers = new Vector.<ISleepWakeupDestroy>();
			_obsLength = 0;
		}
		
		public static function getInstance():IAppNotifier 
		{
			if (_instance == null) _instance = new AppStateNotifier(new SingletonEnforcer());
			
			return _instance;
		}
		
		// ================================================================================================================================
		// ISleepWakeupDestroy
		// ================================================================================================================================
		
		public function sleep():void
		{
			if (_obsLength) {
				for (_counter = 0; _counter < _obsLength; _counter++) {
					_observers[_counter].sleep();
				}
			}
		}
		
		public function wakeup():void
		{
			if (_obsLength) {
				for (_counter = 0; _counter < _obsLength; _counter++) {
					_observers[_counter].wakeup();
				}
			}
		}
		
		public function destroy():void
		{
			if (_obsLength) {
				for (_counter = 0; _counter < _obsLength; _counter++) {
					_observers[_counter].destroy();
				}
			}
			
			_observers = null;
			
			_instance = null;
		}
		
		// ================================================================================================================================
		// IAppNotifier
		// ================================================================================================================================
		
		public function subscribe(observer:ISleepWakeupDestroy):Boolean
		{
			if (observer == null) throw new ArgumentIncompatibleError("observer");
			
			var indxObs:int = _observers.indexOf(observer);
			if (indxObs == -1) {
				_observers.push(observer);
				_obsLength++;
				return true;
			}
			
			return false;
		}
		
		public function unsubscribe(observer:ISleepWakeupDestroy):Boolean
		{
			if (observer == null) throw new ArgumentIncompatibleError("observer");
			
			var indxObs:int = _observers.indexOf(observer);
			if (indxObs > -1) {
				_observers.splice(indxObs, 1);
				_obsLength--;
				return true;
			}
				
			return false;	
		}
	}
}

class SingletonEnforcer {}